#include "reportgenerator.h"
ReportGenerator::ReportGenerator(QObject *parent)
    : QObject(parent)
{
    outParamInit();
    subtitleFont    = QFont("Arial", 10);
    titleFont       = QFont("Arial", 18, QFont::Bold);
    title2Font      = QFont("Arial", 14, QFont::Bold);
    defaultFont     = QFont("Arial", 10);
}

/**
 * @name    generateReport
 * @brief   设置导出pdf文件
 * @param   filename  文件的全路径
 * @return  void
*/
void ReportGenerator::generateReport(const QString &filename){
    outParamInit();
    QPdfWriter writer(filename);
    m_pPdfWritet = &writer;
    writer.setPageSize(QPageSize(QPageSize::A4));
    writer.setPageMargins(QMarginsF(30, 30, 30, 30)); // 设置页边距（单位毫米）
    writer.setTitle("软件测试报告");
    writer.setCreator("Qt Report Generator v1.0");

    QPainter painter;
    m_pPainter = &painter;
    if (!painter.begin(&writer)) {
        qWarning() << "无法打开PDF文件进行写入:" << filename;
        return;
    }


    // 页面尺寸（像素） 8917   13033
    QRect pageRect = writer.pageLayout().paintRectPixels(writer.resolution());
    m_nCurPageMaxY = pageRect.height();
    m_nCurPageMaxWidht = pageRect.width();
    //qDebug()<<"pageRect="<<pageRect;

    //绘制内容
    drawInfo(&painter,pageRect);
    qDebug() << "PDF测试报告已生成:" << filename;
}

/**
 * @name    outPreview
 * @brief   导出预览
 * @param   void
 * @return  QList<QPixmap> 预览图片
*/
QList<QPixmap> ReportGenerator::outPreview()
{
    m_logImages.clear();
    m_nYPos = 0;
    double xPixel = 1024.0;
    double yPixel = xPixel*4;

    //相关系数参数设定
    sizeText    = 20;
    sizeTitle1  = 30;
    sizeTitle2  = 25;
    emptyLine1  = 5;
    legend1     = 10;

    QRect pageRect = QRect(0,0,xPixel,yPixel);
    m_nCurPageMaxY = yPixel;
    m_nCurPageMaxWidht = xPixel;
    QPixmap pixmap(xPixel, yPixel);
    pixmap.fill(Qt::white); // 设置背景颜色为白色

    QPainter painter;
    painter.begin(&pixmap);
    m_pPainter = & painter;
    QPdfWriter writer("");
    m_pPdfWritet = &writer;

    //绘制内容
    drawInfo(&painter,pageRect);

    m_logImages.push_back(pixmap);
    return m_logImages;
}

/**
 * @name    drawReportHeader
 * @brief   写入文档 页眉 页脚 标题 项目信息
 * @param   painter 绘制对象
 * @param   rect 可绘制的区域
 * @return  void
*/
void ReportGenerator::drawReportHeader(QPainter &painter, const QRect &rect) {
    // 设置背景色
    int tWidht = rect.width();
    //int tHeight = rect.height();
    //painter.fillRect(QRect(rect.x(), rect.y(), rect.width(), 400), QColor("#2c3e50"));
    //painter.fillRect(QRect(0,0,tWidht,sizeTitle1),  QColor("#2c3e50"));

    //页眉
    drawSubTitle();
    // 标题
    painter.setPen(Qt::black);
    painter.setFont(titleFont);
    drawTextOnPdf(0,tWidht,sizeTitle1,"气相色谱仪分析检测报告",Qt::AlignCenter);
    addPage(emptyLine1,0);
    // 项目信息
    painter.setFont(title2Font);
    drawTextOnPdf(0,tWidht,sizeTitle2, "项目名称: 气相色谱仪分析XTW");
    drawTextOnPdf(0,tWidht,sizeTitle2, "版本信息: v2.1.5");
}


/**
 * @name    drawSummaryAndCharts
 * @brief   绘制测试项目
 * @param   painter 绘制对象
 * @param   rect 可绘制的区域
 * @return  void
*/
void ReportGenerator::drawSummaryAndCharts(QPainter &painter, const QRect &rect) {
    int tWidht = rect.width();
    addPage(emptyLine1,0);
    painter.setPen(Qt::black);
    painter.setFont(title2Font);
    drawTextOnPdf(0,tWidht,sizeTitle2, "测试摘要");
    // 绘制摘要信息
    painter.setFont(subtitleFont);
    QString conclusionText =
            "测试周期: 2023-07-15 至"+
            QDate::currentDate().toString("yyyy-MM-dd")+"\n"
                                                        "测试负责人: 张工\n"
                                                        "总用例数: 256\n"
                                                        "已执行用例: 256 (100%)\n"
                                                        "用例通过率: 93.4%";
    // 绘制多行文本
    QTextOption option;
    option.setWrapMode(QTextOption::WordWrap);
    painter.drawText(QRectF(0, m_nYPos, rect.width(), sizeText*7), conclusionText, option);
    addPage(sizeText*5,sizeText);

    // 绘制通过率饼图
    drawPieChart(painter, rect.width() / 2, m_nYPos, rect.width() / 4);
    // 绘制问题类型图表
    drawBarChart(painter, 0, m_nYPos, rect.width(), rect.width()/3);
}

/**
 * @name    drawPieChart
 * @brief   绘制饼图
 * @param   painter 绘制对象
 * @param   x 水平方向起始位置
 * @param   y 垂直方向起始位置
 * @param   size 显示区域大小 为size*size的大小范围
 * @return  void
*/
void ReportGenerator::drawPieChart(QPainter &painter, int x, int y, int size) {

    addPage(0,size+sizeText);
    // 通过率数据 (93.4%通过)
    qreal passed = 93.4;
    qreal failed = 6.6;

    // 绘制饼图背景圆
    painter.setPen(QPen(Qt::darkGray, 1));
    painter.setBrush(Qt::NoBrush);
    painter.drawEllipse(x, y+sizeText, size, size);

    // 绘制通过部分
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor("#2ecc71")); // 绿色表示通过
    painter.drawPie(x, y+sizeText, size, size, 0, static_cast<int>(passed * 16 * 3.6));

    // 绘制失败部分
    painter.setBrush(QColor("#e74c3c")); // 红色表示失败
    painter.drawPie(x, y+sizeText, size, size, static_cast<int>(passed * 16 * 3.6),
                    static_cast<int>(failed * 16 * 3.6));

    // 添加图例
    QFont legendFont("Arial", 9);
    painter.setFont(legendFont);
    painter.setPen(Qt::black);

    painter.setBrush(QColor("#2ecc71"));
    int alignY = (sizeText - legend1)/2;
    int interalY = legend1*1.2;
    painter.drawRect(x + size , y+alignY , legend1, legend1);
    painter.drawText(QRect(x+ size+interalY,y,size,sizeText),Qt::AlignLeft | Qt::AlignVCenter, QString::number(passed, 'f', 1) + "% 通过");

    painter.setBrush(QColor("#e74c3c"));
    painter.drawRect(x + size , y + sizeText+alignY, legend1, legend1);
    painter.drawText(QRect(x+ size+interalY,y+sizeText,size,sizeText),Qt::AlignLeft| Qt::AlignVCenter, QString::number(failed, 'f', 1) + "% 失败");

    // 添加标题
    QFont titleFont("Arial", 11, QFont::Bold);
    painter.setFont(titleFont);
    painter.drawText(QRect(x,y,m_nCurPageMaxWidht,sizeText),Qt::AlignLeft,"用例通过率统计");
    addPage(size+sizeText,0);
}

/**
 * @name    drawBarChart
 * @brief   绘制直方图
 * @param   painter 绘制对象
 * @param   x 水平方向起始位置
 * @param   y 垂直方向起始位置
 * @param   width 宽度
 * @param   height 高度
 * @return  void
*/
void ReportGenerator::drawBarChart(QPainter &painter, int x, int y, int width, int height){

    addPage(0,height+sizeTitle2);
    // 图表标题
    x+=sizeTitle2;
    QFont titleFont("Arial", 11, QFont::Bold);
    painter.setFont(titleFont);
    painter.drawText(QRect(0,y,width,sizeTitle2),Qt::AlignLeft, "缺陷类型分布");

    //给Y轴的轴刻度留出位置
    y += sizeTitle2;
    width -= sizeTitle2;

    // 图表边框
    painter.setPen(QPen(Qt::black, 1));
    painter.drawRect(x, y, width, height);

    // Y轴标签
    painter.setPen(Qt::darkGray);
    painter.setFont(QFont("Arial", 9));

    // X轴坐标
    int barWidth = (width - 60) / 5; // 5种问题类型
    QStringList categories = {"UI问题", "功能缺陷", "性能问题", "兼容性", "安全问题"};

    QList<int> values = {26, 45, 18, 12, 5}; // 各类型缺陷数量
    int maxValue = *std::max_element(values.begin(), values.end());
    int barWidhtShow = barWidth- 50;

    // Y轴刻度
    int yInterval = height / 5;
    for (int i = 0; i <= 5; i++) {
        int yPos = y + height - (i * yInterval);
        painter.drawLine(x , yPos, x-sizeTitle2, yPos);
        painter.drawText(QRect(x-sizeTitle2,yPos,width,sizeTitle2),Qt::AlignLeft, QString::number(maxValue * (i*0.2)));
    }

    // X轴刻度
    for (int i = 0; i < categories.size(); i++) {
        int xPos = x + 40 + (i * barWidth);
        painter.drawText(QRect(xPos,y + height + legend1,barWidhtShow,sizeTitle2),Qt::AlignCenter, categories[i]);
    }

    // 绘制柱状图
    painter.setPen(Qt::NoPen);
    QLinearGradient gradient(0, 0, 0, height);
    gradient.setColorAt(0, QColor("#3498db"));
    gradient.setColorAt(1, QColor("#2980b9"));

    for (int i = 0; i < categories.size(); i++) {
        int barHeight = static_cast<int>(values[i] * 1.0 / maxValue * (height - 20));
        int barX = x + 40 + (i * barWidth);
        int barY = y + height - barHeight;

        painter.setBrush(gradient);
        painter.drawRect(barX, barY, barWidhtShow, barHeight);

        // 在柱状图上显示数值
        painter.setPen(Qt::black);
        painter.drawText(QRect(barX, barY - 5 ,barWidhtShow,sizeTitle2),Qt::AlignCenter,QString::number(values[i]));
        painter.setPen(Qt::NoPen);
    }
    addPage(height+sizeTitle2*3,0);
}

/**
 * @name    drawTestResultsTable
 * @brief   表格数据导出
 * @param   painter 绘制对象
 * @param   rect 可绘制的区域
 * @return  void
*/
void ReportGenerator::drawTestResultsTable(QPainter &painter, const QRect &rect, QPdfWriter &writer) {
    Q_UNUSED(writer)
    // 表格标题
    QFont sectionFont("Arial", 14, QFont::Bold);
    painter.setFont(sectionFont);
    painter.setPen(Qt::black);
    painter.drawText(rect.x(), rect.y() + 30, "详细测试结果");

    // 创建表格
    QTextDocument doc;
    doc.setDefaultFont(QFont("Arial", 10));

    QTextTable *table = new QTextTable(&doc); //doc.rootFrame()->lastCursor().insertTable(11, 5);

    // 设置表格属性
    QTextTableFormat tableFormat;
    tableFormat.setAlignment(Qt::AlignCenter);
    tableFormat.setCellPadding(5);
    tableFormat.setCellSpacing(0);
    tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
    tableFormat.setBorder(0.5);
    //table->setFormat(tableFormat);

    // 设置表头格式
    QTextCharFormat headerFormat;
    headerFormat.setFontWeight(QFont::Bold);
    headerFormat.setBackground(QColor("#ecf0f1"));

    // 填充表头
    QTextCursor cursor = table->cellAt(0, 0).firstCursorPosition();
    cursor.insertText("用例ID", headerFormat);

    cursor = table->cellAt(0, 1).firstCursorPosition();
    cursor.insertText("测试模块", headerFormat);

    cursor = table->cellAt(0, 2).firstCursorPosition();
    cursor.insertText("测试用例", headerFormat);

    cursor = table->cellAt(0, 3).firstCursorPosition();
    cursor.insertText("执行结果", headerFormat);

    cursor = table->cellAt(0, 4).firstCursorPosition();
    cursor.insertText("备注", headerFormat);

    // 填充表格数据
    QStringList results = {"通过", "失败", "阻塞"};
    QStringList modules = {"用户管理", "数据导入", "分析引擎", "报表生成", "系统设置"};

    for (int row = 1; row < 10; row++) {
        QTextCharFormat cellFormat;

        // 为失败行设置不同背景色
        QString result = results[QRandomGenerator::global()->bounded(3)];
        if (result == "失败") cellFormat.setBackground(QColor(255, 231, 230));
        if (result == "阻塞") cellFormat.setBackground(QColor(255, 246, 217));

        cursor = table->cellAt(row, 0).firstCursorPosition();
        cursor.insertText(QString("TC-%1").arg(row + 1000), cellFormat);

        cursor = table->cellAt(row, 1).firstCursorPosition();
        cursor.insertText(modules[QRandomGenerator::global()->bounded(5)], cellFormat);

        cursor = table->cellAt(row, 2).firstCursorPosition();
        cursor.insertText(QString("测试用例描述 #%1").arg(row + 100), cellFormat);

        cursor = table->cellAt(row, 3).firstCursorPosition();
        cursor.insertText(result, cellFormat);

        cursor = table->cellAt(row, 4).firstCursorPosition();
        QString note = (result == "失败") ? "详见BUG-202307" + QString::number(QRandomGenerator::global()->bounded(100))
                                        : "无";
        cursor.insertText(note, cellFormat);
    }

    // 调整列宽比例
    QVector<QTextLength> constraints;
    constraints << QTextLength(QTextLength::PercentageLength, 15);
    constraints << QTextLength(QTextLength::PercentageLength, 20);
    constraints << QTextLength(QTextLength::PercentageLength, 35);
    constraints << QTextLength(QTextLength::PercentageLength, 15);
    constraints << QTextLength(QTextLength::PercentageLength, 15);
    tableFormat.setColumnWidthConstraints(constraints);
    table->setFormat(tableFormat);

    // 渲染表格
    int tableHeight = doc.size().height();
    doc.drawContents(&painter, QRectF(rect.x(), rect.y() + 50, rect.width(), rect.height() - 50));

    // 移动绘画位置到表格底部
    painter.translate(0, tableHeight + 60);
}

/**
 * @name    drawEnvironmentInfo
 * @brief   绘制测试条件信息
 * @param   painter 绘制对象
 * @param   rect 可绘制的区域
 * @return  void
*/
void ReportGenerator::drawEnvironmentInfo(QPainter &painter, const QRect &rect) {
    int tWidht = rect.width();
    //标题
    // 设置边框
    //    painter.setPen(QPen(Qt::lightGray, 1));
    //    painter.setBrush(QColor(245, 248, 250));
    //    painter.drawRoundedRect(QRect(0,m_nYPos,tWidht,sizeTitle2), 5, 5);

    painter.setFont(title2Font);
    painter.setPen(Qt::black);
    drawTextOnPdf(0,tWidht,sizeTitle2, "测试环境信息");
    // 内容格式
    painter.setFont(subtitleFont);
    painter.setPen(Qt::black);


    // 第1列 // 第2列
    drawTextOnPdf(0,tWidht,sizeText,"操作系统: Windows 11 专业版",Qt::AlignLeft,false);
    drawTextOnPdf(tWidht/2,tWidht,sizeText,"数据库: MySQL 8.0",Qt::AlignLeft);

    drawTextOnPdf(0,tWidht,sizeText,"处理器: Intel Core i7-12700H",Qt::AlignLeft,false);
    drawTextOnPdf(tWidht/2,tWidht,sizeText,"测试工具: Selenium + JUnit",Qt::AlignLeft);

    drawTextOnPdf(0,tWidht,sizeText,"内存: 32GB DDR5",Qt::AlignLeft,false);
    drawTextOnPdf(tWidht/2,tWidht,sizeText,"浏览器: Chrome 114.0.5735.199",Qt::AlignLeft);

    drawTextOnPdf(0,tWidht,sizeText,"图形卡: NVIDIA RTX 3060",Qt::AlignLeft,false);
    drawTextOnPdf(tWidht/2,tWidht,sizeText,"网络环境: 千兆以太网",Qt::AlignLeft);
}

/**
 * @name    drawConclusion
 * @brief   报告总结
 * @param   painter 绘制对象
 * @param   rect 可绘制的区域
 * @return  void
*/
void ReportGenerator::drawConclusion(QPainter &painter, const QRect &rect) {
    int tWidht = rect.width();
    QFont sectionFont("Arial", 14, QFont::Bold);
    painter.setFont(sectionFont);
    painter.setPen(Qt::black);
    painter.drawText(QRect(0,m_nYPos,tWidht,sizeTitle2),Qt::AlignLeft, "测试结论与评审");
    m_nYPos+= sizeTitle2;

    QFont contentFont("Arial", 10);
    painter.setFont(contentFont);

    QString conclusionText =
            "本次测试针对智能数据分析平台v2.1.5版本进行了全面验证，执行全部256个测试用例。"
            "测试结果表明：\n"
            "   - 主要功能模块已实现需求文档要求的功能\n"
            "   - 发现关键缺陷18个（其中严重问题3个，主要问题10个）\n"
            "   - 性能指标达到预期要求\n"
            "   - UI界面存在局部不一致问题\n\n"
            "综合评估：软件质量基本达到发布标准，但需修复所有严重及以上缺陷后方可上线。";

    // 绘制多行文本
    QTextOption option;
    option.setWrapMode(QTextOption::WordWrap);
    painter.drawText(QRectF(0, m_nYPos, rect.width(), sizeText*7), conclusionText, option);
    addPage(sizeText*6,sizeText);

    addPage(sizeText,sizeText);
    // 签名区域
    painter.drawText(QRect(0,m_nYPos,tWidht,sizeText),Qt::AlignLeft, "测试负责人: ________________________");
    painter.drawText(QRect(0+tWidht/2,m_nYPos,tWidht,sizeText),Qt::AlignLeft, "日期: ________________________");
    addPage(sizeText,sizeText);

}

/**
 * @name    addPage
 * @brief   设置导出pdf文件
 * @param   pos 移动的位置
 * @return  void
*/
void ReportGenerator::addPage(int pos,int height)
{
    if(!m_pPdfWritet) return;
    if(m_nYPos + pos  + height >= m_nCurPageMaxY){
        m_nYPos = 0;
        m_pPdfWritet->newPage();
        m_nCurPageCount++;
        //页眉
        drawSubTitle();
    }else{
        m_nYPos += pos;
    }
}

/**
 * @name    drawTextOnPdf
 * @brief   绘制文本信息
 * @param   x 水平方向起始位置
 * @param   w 绘制文本宽度
 * @param   h 绘制文本高度
 * @param   text 文本显示信息
 * @param   flag 文本居中类型
 * @param   autoMove 是否进行Y坐标的自动移动到下一行
 * @return  void
*/
void ReportGenerator::drawTextOnPdf(int x,int w, int h, QString text, Qt::AlignmentFlag flag,bool autoMove)
{
    if(!m_pPainter) return;
    addPage(0,h);
    m_pPainter->drawText(QRect(x,m_nYPos,w,h),flag, text);
    if(autoMove){
        m_nYPos += h;
    }
}
/**
 * @name    drawSubTitle
 * @brief   绘制 页脚 页眉 信息
 * @param   void
 * @return  void
*/
void ReportGenerator::drawSubTitle()
{
    if(!m_pPainter) return;
    // 副标题
    m_pPainter->setPen(Qt::black);
    m_pPainter->setFont(subtitleFont);
    drawTextOnPdf(20,m_nCurPageMaxWidht,sizeText,"生成日期: " + QDate::currentDate().toString("yyyy-MM-dd"));

    // 横线分隔
    m_pPainter->setPen(QPen(Qt::gray, 0.5));
    m_pPainter->drawLine(0, m_nYPos, m_nCurPageMaxWidht, m_nYPos);
    m_nYPos += emptyLine1;

    // 页脚
    int yPos = m_nCurPageMaxY;
    QFont footerFont("Arial", 9);
    m_pPainter->setFont(footerFont);
    m_pPainter->setPen(Qt::black);
    m_pPainter->drawText(QRect(0,yPos,m_nCurPageMaxWidht,sizeText),Qt::AlignLeft, QString("第 %1 页").arg(m_nCurPageCount));
    m_pPainter->drawText(QRect(0+m_nCurPageMaxWidht/2,yPos,m_nCurPageMaxWidht/2,sizeText),Qt::AlignRight, "PGC Report Generator v1.0");
}

void ReportGenerator::outParamInit()
{
    m_nYPos     = 0;
    sizeText    = 200;
    sizeTitle1  = 300;
    sizeTitle2  = 250;

    emptyLine1  = 50;
    legend1     = 100;
    m_pPdfWritet = nullptr;
    m_nCurPageMaxY = 0;
    m_nCurPageMaxWidht = 0;
    m_pPainter = nullptr;
    m_nCurPageCount = 1;
}

void ReportGenerator::drawSampleTable(QPainter &painter, const QRect &area)
{
    std::vector<std::string> headers;
    std::vector<std::vector<std::string>> tableData;

    // 初始化表格数据
    headers = {"序号", "组分", "浓度", "RSD"};

    tableData.push_back({"001", "甲烷", "28", "Engineer"});
    tableData.push_back({"002", "乙烷", "32", "Designer"});
    tableData.push_back({"003", "乙烯", "24", "Developer"});
    tableData.push_back({"004", "乙炔", "45", "Manager"});

    // 设置字体
    QFont headerFont("Arial", 10, QFont::Bold);
    QFont cellFont("Arial", 9);

    // 计算列宽（根据窗口宽度自动调整）
    int colCount = headers.size();
    std::vector<int> colWidths(colCount);
    int totalWidth = area.width() - 0; // 减去边距
    for (int i = 0; i < colCount; ++i) {
        colWidths[i] = totalWidth / colCount;
    }

    // 设置表格尺寸参数
    const int rowHeight = area.width()/32;
    const int headerHeight = rowHeight;
    const int startX = 0;
    int startY = m_nYPos;

    // 绘制表头背景
    painter.setBrush(QColor(220, 220, 220));
    painter.setPen(Qt::NoPen);
    painter.drawRect(startX, startY, totalWidth, headerHeight);

    // 绘制表头
    painter.setFont(headerFont);
    painter.setPen(Qt::black);
    int xPos = startX;
    for (int col = 0; col < colCount; ++col) {
        QRect headerRect(xPos, startY, colWidths[col], headerHeight);
        painter.setPen(Qt::black);
        painter.drawText(headerRect, Qt::AlignCenter, QString::fromStdString(headers[col]));

        // 绘制列分隔线
        painter.setPen(QColor(150, 150, 150));
        painter.drawLine(headerRect.right(), startY, headerRect.right(), startY + headerHeight);
        xPos += colWidths[col];
    }

    // 绘制行数据
    painter.setFont(cellFont);
    startY += headerHeight;

    for (size_t row = 0; row < tableData.size(); ++row) {
        const auto &rowData = tableData[row];
        int yPos = startY + row * rowHeight;

        // 交替行背景色
        painter.setBrush(row % 2 == 0 ? QColor(245, 245, 245) : Qt::white);
        painter.setPen(Qt::NoPen);
        painter.drawRect(startX, yPos, totalWidth, rowHeight);

        // 绘制单元格文本
        painter.setPen(Qt::black);
        xPos = startX;
        for (int col = 0; col < colCount; ++col) {
            QRect cellRect(xPos, yPos, colWidths[col], rowHeight);
            // 绘制单元格边框
            painter.setPen(QColor(0, 0, 0));
            painter.drawRect(xPos, yPos, colWidths[col], rowHeight);

            painter.drawText(cellRect, Qt::AlignCenter, QString::fromStdString(rowData[col]));
            xPos += colWidths[col];
        }
    }
}

void ReportGenerator::drawInfo(QPainter *painter, QRect pageRect)
{
    // 设置默认字体
    painter->setFont(defaultFont);
    painter->setRenderHint(QPainter::Antialiasing);
    painter->setRenderHint(QPainter::TextAntialiasing);

    // 绘制报告头部
    drawReportHeader(*painter, pageRect);

    // 绘制摘要和图表
    drawSummaryAndCharts(*painter, pageRect);

    // 绘制详细测试结果表格
    //drawTestResultsTable(*painter, pageRect, *m_pPdfWritet);

    // 绘制环境信息
    drawEnvironmentInfo(*painter, pageRect);

    // 绘制结论
    drawConclusion(*painter, pageRect);

    drawSampleTable(*painter, pageRect);

    painter->end();
}

